#ifndef __FOC_H
#define __FOC_H

#include "stdint.h"

//extern volatile uint32_t gFoc_TimeCNT;

#define FOC_SQRT_3 1.73205f
#define FOC_ANGLE_TO_RADIN 0.01744f //2*pi / 360
#define AD_TO_CURRENT 0.00488f   //16.5 times

#define M_OUTMAX  1.0f
#define M_KP  0.06f
#define M_KI  0.08f
#define M_KD  0.0f

#define FILTER_KP 0.8f      //一介低通滤波系数

#define TIM2_CNT_CENT 10000
#define TIM2_CNT_ZERO 0
#define TIM2_ENCODER_PLUSE_ONE_CYCLE 2000 //one thouthand pulses per circle, quadraple frequence

//increment pi regulator
typedef struct 
{
    /* data */
    float kp;
    float ki;
    float kd;

    float pre;
    float tar;
    float bias;
    float lastBias;
    float out;
    float out_temp;
    float outMax;
}PI_Struct;


//foc struct
typedef struct
{
    uint8_t isEnable;   //motor enable
    uint8_t polePairs;  //polar pairs

    float tariq;        //target current D
    float tarid;        //target current Q
    float angle;        //angle 0~360
    float radian;       //w 0~2*pi
    float radian_temp;  //for test

    uint8_t iNum;       //a number of res shuntor
    float ia;           //a
    float ib;           //b
	float ic;           //b
    float ialpha;       //clarke * 2/3 ialpha
    float ibeta;        //clarke *2/3 ibeta
    float iq;           //park Iq
    float id;           //park Id

    float ialpha_SVPWM;      //depark iapha
    float ibeta_SVPWM;      //depark ibeta

    PI_Struct idPID;
    PI_Struct iqPID;

    void (*SetEnable)(uint8_t isEnable);        //
    float (*GetEncoderAngle)(void);
    uint8_t (*GetSVPWMSector)(void);
    void (*GetPreCurrent)(float *ua,float *ub,float *uc);
    void (*SvpwmGenerate)(float ualhpa,float ubeta);

}SFOC_Struct, FOC_Struct, *PFOC_Struct;


/*************************************************************
** Function name:       FOC_EXPORT
** Descriptions:        声明一个FOC对象
**                      xGetPreCurrent：获取相电流值，注意检测时间窗口
**						xiNum：电流采集相数（主要用来区分是否为3相电流）
**                      xSvpwmGenerate：SVPWM生成函数。配合SVPWM.h
** Input parameters:    None
** Output parameters:   None
** Returned value:      None
** Remarks:             None
*************************************************************/
#define FOC_EXPORT(x,xpolePairs,xiNum,xSetEnable,xGetEncoderAngle,xGetSVPWMSector,xGetPreCurrent,xSvpwmGenerate)    \
FOC_Struct x = {                            \
    .isEnable = 0,                          \
    .polePairs = xpolePairs,                \
    .tarid = 0.0,                           \
    .tariq = 1.0,                           \
    .angle = 0.0,                           \
    .radian = 0.0,                          \
    .iNum = xiNum,                          \
    .ia = 0.0,                              \
    .ib = 0.0,                              \
    .ic = 0.0,                              \
    .ialpha = 0.0,                              \
    .ibeta = 0.0,                               \
    .iq = 0.0,                              \
    .id = 0.0,                              \
    .ialpha_SVPWM = 0.0,                         \
    .ibeta_SVPWM = 0.0,                         \
    .idPID = {0},                           \
    .iqPID = {0},                           \
    .SetEnable = xSetEnable,          \
    .GetEncoderAngle = xGetEncoderAngle,    \
    .GetSVPWMSector = xGetSVPWMSector,      \
    .GetPreCurrent = xGetPreCurrent,        \
    .SvpwmGenerate = xSvpwmGenerate,        \
};


typedef struct 
{
    float ualpha;		//阿尔法轴目标电压 	(最大值为母线电压 * sqrt(3) / 3)
    float ubeta;		//贝塔轴目标电压   	(最大值为母线电压 * sqrt(3) / 3)
    float u1;		    //用于扇区判断
    float u2;		    //用于扇区判断
    float u3;		    //用于扇区判断
    float t0;		    //0矢量作用时长
    float t1;		    //1矢量作用时长
    float t2;		    //2矢量作用时长
    float t3;		    //3矢量作用时长
    float t4;		    //4矢量作用时长
    float t5;		    //5矢量作用时长
    float t6;		    //6矢量作用时长
    float t7;		    //7矢量作用时长
    float ts;		    //SVPWM周期
	float maxTs;        //高电平最长时间
	float adcTs;        //ADC稳定时间
    float udc;		    //母线电压
    uint8_t sector;      //扇区索引

    void (*SetChannelAHighLeaveTime_us)(float time); //一个SVPWM周期内A相绕组高电平时间(中央对齐方式)
    void (*SetChannelBHighLeaveTime_us)(float time); //一个SVPWM周期内B相绕组高电平时间(中央对齐方式)
    void (*SetChannelCHighLeaveTime_us)(float time); //一个SVPWM周期内C相绕组高电平时间(中央对齐方式)
    void (*SetChannelDHighLeaveTime_us)(float time); //一个SVPWM周期内C相绕组高电平时间(中央对齐方式)
}Svpwm_Struct,*PSvpwm_Struct;


typedef struct  {
    int32_t Tim2Cnt;        //编码器脉冲数 0-360°
    float angle;			//编码器角度 0-360°
}TimEnc_Struct, *PTimEnc_Struct;



/*************************************************************
** Function name:       SVPWM_EXPORT
** Descriptions:        初始化一个SVPMW对象
** Input parameters:    x:对象名字
**                      xTs：SVPWM波形周期 单位us 建议 100
**                      xMaxTs：高电平最长时间 建议80 留20us给AD采样
**						xAdcTs：ADC稳定时间 建议1us
**                      xudc：母线电压 单位V 
**                      xSetChannelAHighLeaveTime_us：设置A相高电平时间
**                      xSetChannelBHighLeaveTime_us：设置B相高电平时间
**                      xSetChannelCHighLeaveTime_us：设置C相高电平时间
** Output parameters:   None
** Returned value:      None
** Remarks:             None
*************************************************************/
#define SVPWM_EXPORT(x,xTs,xMaxTs,xAdcTs,xudc,xSetChannelAHighLeaveTime_us,xSetChannelBHighLeaveTime_us,xSetChannelCHighLeaveTime_us,xSetChannelDHighLeaveTime_us)     \
Svpwm_Struct x = {                      \
    .ualpha = 0,                            \
    .ubeta = 0,                            \
    .u1 = 0,                            \
    .u2 = 0,                            \
    .u3 = 0,                            \
    .t0 = 0,                            \
    .t1 = 0,                            \
    .t2 = 0,                            \
    .t3 = 0,                            \
    .t4 = 0,                            \
    .t5 = 0,                            \
    .t6 = 0,                            \
    .t7 = 0,                            \
    .ts = xTs,                          \
	.maxTs = xMaxTs,                    \
	.adcTs = xAdcTs,                    \
    .udc = xudc,                        \
    .sector = 0,                        \
    .SetChannelAHighLeaveTime_us = xSetChannelAHighLeaveTime_us,            \
    .SetChannelBHighLeaveTime_us = xSetChannelBHighLeaveTime_us,            \
    .SetChannelCHighLeaveTime_us = xSetChannelCHighLeaveTime_us,            \
    .SetChannelDHighLeaveTime_us = xSetChannelDHighLeaveTime_us,            \
};


typedef struct{
	uint16_t adDmaValue[9];
	int adValue[3];
	int lastAdValue[3];
    float ia, ib, ic;
}SADC1_Struct;


void FocContorl(PFOC_Struct pFOC);
void SetCurrentPIDTar(PFOC_Struct pFOC,float tarid,float tariq);
void SetCurrentPIDParams(PFOC_Struct pFOC,float kp,float ki,float kd,float outMax);
void SetFocEnable(PFOC_Struct pFOC,uint8_t isEnable);
void FOCPrintf(PFOC_Struct pFOC);

void SvpwmContorol(PSvpwm_Struct pSvpwm,float ualpha,float ubeta);
uint8_t GetSVPWMSector(PSvpwm_Struct pSvpwm);
void foc_test_init(void);
void foc_test(void);
void foc_test_printf(void);
#endif
